package com.score;

import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.util.Log;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

public class Mp3Decoder {
    private String OUTPUT_FILE = "";

    public String decodeMP3ToPCM(String mp3FilePath) throws IOException {
        String imageDir = DirManager.getImageDir();
        File file = new File(imageDir + "/output.pcm");
        OUTPUT_FILE = file.getAbsolutePath();

        MediaExtractor extractor = new MediaExtractor();
        extractor.setDataSource(mp3FilePath);

        MediaFormat format = null;
        int trackIndex = selectTrack(extractor);
        if (trackIndex >= 0) {
            format = extractor.getTrackFormat(trackIndex);
            extractor.selectTrack(trackIndex);
        }

        MediaCodec codec = MediaCodec.createDecoderByType(format.getString(MediaFormat.KEY_MIME));
        codec.configure(format, null, null, 0);
        codec.start();

        ByteBuffer[] inputBuffers = codec.getInputBuffers();
        ByteBuffer[] outputBuffers = codec.getOutputBuffers();
        MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();

        FileOutputStream outputStream = new FileOutputStream(new File(OUTPUT_FILE));

        boolean sawInputEOS = false;
        boolean sawOutputEOS = false;
        while (!sawOutputEOS) {
            if (!sawInputEOS) {
                int inputBufferIndex = codec.dequeueInputBuffer(-1);
                if (inputBufferIndex >= 0) {
                    ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
                    int sampleSize = extractor.readSampleData(inputBuffer, 0);
                    if (sampleSize < 0) {
                        codec.queueInputBuffer(inputBufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
                        sawInputEOS = true;
                    } else {
                        codec.queueInputBuffer(inputBufferIndex, 0, sampleSize, extractor.getSampleTime(), 0);
                        extractor.advance();
                    }
                }
            }

            int outputBufferIndex = codec.dequeueOutputBuffer(info, -1);
            if (outputBufferIndex >= 0) {
                ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];
                byte[] chunk = new byte[info.size];
                outputBuffer.get(chunk);
                outputBuffer.clear();

                // Write PCM data to file
                outputStream.write(chunk);

                codec.releaseOutputBuffer(outputBufferIndex, false);
                if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                    sawOutputEOS = true;
                }
            } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
                // Subsequent data will conform to new format
            }
        }

        codec.stop();
        codec.release();
        extractor.release();
        outputStream.close();

        return file.getAbsolutePath();
    }

    private int selectTrack(MediaExtractor extractor) {
        // Select the first audio track we find.
        int numTracks = extractor.getTrackCount();
        for (int i = 0; i < numTracks; i++) {
            MediaFormat format = extractor.getTrackFormat(i);
            String mime = format.getString(MediaFormat.KEY_MIME);
            if (mime.startsWith("audio/")) {
                return i;
            }
        }
        return -1;
    }
}

